package com.szxb.facebus.task.remote;

import android.os.Environment;
import android.text.TextUtils;

import com.alibaba.fastjson.JSONObject;
import com.example.zhoukai.modemtooltest.ModemToolTest;
import com.example.zhoukai.modemtooltest.NvConstants;
import com.google.gson.Gson;
import com.szxb.facebus.BuildConfig;
import com.szxb.facebus.BusApp;
import com.szxb.facebus.db.entity.bean.CheckResponse;
import com.szxb.facebus.intrefaces.OnDownProgress;
import com.szxb.facebus.net.http.JsonRequest;
import com.szxb.facebus.util.basics.Config;
import com.szxb.facebus.util.basics.Utils;
import com.szxb.facebus.util.rx.MainLooper;
import com.szxb.facebus.util.schedule.ThreadFactory;
import com.szxb.mlog.SLog;
import com.yanzhenjie.nohttp.rest.Response;
import com.yanzhenjie.nohttp.rest.SyncRequestExecutor;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;


/**
 * 作者：Tangren on 2018-09-19
 * 包名：com.szxb.jcbus.task.work
 * 邮箱：996489865@qq.com
 * TODO:一句话描述
 */

public class CheckApkThread extends Thread {

    private AtomicBoolean isRun = new AtomicBoolean(false);

    @Override
    public void run() {
        super.run();
        try {
            int isDownFinish = BusApp.getPosManager().isDownFinish();
            if (isDownFinish > 0) {
                //如果下载完成则return
                SLog.d("CheckApkThread(run.java:55)已下载完成,关闭任务");
                ThreadFactory.getScheduledPool().stopTask("loop_check");
                return;
            }

            if (isRun.get()) {
                return;
            }

            String item = ModemToolTest.getItem(NvConstants.REQUEST_GET_SN);
            JsonRequest checkRequest = new JsonRequest(Config.URL_CHECK_VERSION);
            checkRequest.set("devno", item);
            checkRequest.set("appname", "face_bus_app");
            Response<JSONObject> execute = SyncRequestExecutor.INSTANCE.execute(checkRequest);
            if (execute.isSucceed()) {
                CheckResponse checkResponse = new Gson().fromJson(execute.get().toJSONString(), CheckResponse.class);
                if (checkResponse.isSuccess()) {
                    List<CheckResponse.DataBean> data = checkResponse.data;
                    if (data.size() > 0) {
                        CheckResponse.DataBean dataBean = data.get(0);
                        if (TextUtils.equals(dataBean.getUPDATE_MODE(), "0")) {
                            SLog.d("CheckApkThread(run.java:75)后台配置不更新");
                            ThreadFactory.getScheduledPool().stopTask("loop_check");
                            return;
                        }
                        if (!TextUtils.equals(dataBean.getAPPRMK(), BuildConfig.VERSION_NAME)) {
                            isRun.set(true);
                            SLog.d("CheckApkThread(run.java:77)开始下载");
                            exeDownTask(checkResponse.getFtpurl(), checkResponse.getFtpport(),
                                    checkResponse.getFtpuser(), checkResponse.getFtppwd(),
                                    "bus/" + dataBean.getAPPFILE(), Environment.getExternalStorageDirectory() + "/" + dataBean.getAPPFILE(), false, dataBean.getUPDATE_EFFECT(), dataBean.getAPPRMK());
                            isRun.set(false);
                        } else {
                            //无需更新
                            SLog.d("CheckApkThread(run.java:82)无需更新");
                            ThreadFactory.getScheduledPool().stopTask("loop_check");
                        }
                    }
                } else {
                    SLog.e("CheckApkThread(run.java:96)" + checkResponse.getResult());
                    ThreadFactory.getScheduledPool().stopTask("loop_check");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            SLog.e("CheckApkThread(run.java:90)" + Utils.getExectionStr(e));
            errorCallBack("IO异常");
        }
    }

    private FTPClient client = new FTPClient();

    private OnDownProgress onDownProgress;

    public void setOnDownProgress(OnDownProgress onDownProgress) {
        this.onDownProgress = onDownProgress;
    }

    private boolean connect(String ip, int port, String userName, String psw) throws IOException {
        client.connect(ip, port);
        client.setControlEncoding("GBK");
        if (FTPReply.isPositiveCompletion(client.getReplyCode())) {
            if (client.login(userName, psw)) {
                return true;
            }
        }
        disconnect();
        return false;
    }

    /**
     * @param remote  服务端路径
     * @param local   本地保存的路径
     * @param isRange 是否支持断点继续
     * @throws IOException .
     */
    private void exeDownTask(String ip, int port, String userName, String psw,
                             String remote, String local, boolean isRange, String effWay, String webVersion) throws IOException {

        boolean connect = connect(ip, port, userName, psw);
        if (!connect) {
            errorCallBack("FTP连接失败");
            return;
        }
        client.enterLocalActiveMode();
        client.setFileType(FTP.BINARY_FILE_TYPE);
        FTPFile[] files = client.listFiles(remote);
        if (files.length != 1) {
            errorCallBack("文件不存在");
            return;
        }

        long lRemoteSize = files[0].getSize();
        File f = new File(local);
        //本地存在文件，进行断点下载
        if (f.exists() && isRange) {
            long localSize = f.length();
            //判断本地文件大小是否大于远程文件大小
            if (localSize >= lRemoteSize) {
                errorCallBack("本地文件大于远程文件");
                return;
            }
            //进行断点续传，并记录状态
            FileOutputStream out = new FileOutputStream(f, true);
            client.setRestartOffset(localSize);
            InputStream in = client.retrieveFileStream(remote);
            byte[] bytes = new byte[1024];
            long step = lRemoteSize / 100;
            long process = localSize / step;
            int c;

            while ((c = in.read(bytes)) != -1) {
                out.write(bytes, 0, c);
                localSize += c;
                long nowProcess = localSize / step;
                if (nowProcess > process) {
                    process = nowProcess;
                    progressCallBack(process);
                }
            }
            in.close();
            out.close();
            boolean isDo = client.completePendingCommand();
            if (isDo) {
                finishCallBack(local, webVersion, effWay);
            } else {
                errorCallBack("下载失败");
            }
            disconnect();
        } else {
            if (f.exists()) {
                boolean delete = f.delete();
            }
            OutputStream out = new FileOutputStream(f);
            InputStream in = client.retrieveFileStream(remote);
            byte[] bytes = new byte[1024];
            long step = lRemoteSize / 100;
            long process = 0;
            long localSize = 0L;
            int c;
            while ((c = in.read(bytes)) != -1) {
                out.write(bytes, 0, c);
                localSize += c;
                long nowProcess = localSize / step;
                if (nowProcess > process) {
                    process = nowProcess;
                    progressCallBack(process);
                }
            }
            in.close();
            out.close();
            boolean upNewStatus = client.completePendingCommand();
            if (upNewStatus) {
                finishCallBack(local, webVersion, effWay);
            } else {
                errorCallBack("下载失败");
            }
            disconnect();
        }
    }

    private void disconnect() throws IOException {
        if (client.isConnected()) {
            client.disconnect();
        }
    }


    private void errorCallBack(String result) {
        if (onDownProgress != null) {
            onDownProgress.onDownloadError(0, result);
        }
    }

    private void progressCallBack(long progress) {
        if (onDownProgress != null) {
            onDownProgress.onProgress(0, (int) progress, 0, 0);
        }
    }

    private void finishCallBack(final String filePath, final String apkVersion, final String effWay) {
        if (onDownProgress != null) {
            MainLooper.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onDownProgress.onFinish(0, filePath, apkVersion, effWay);
                }
            });
        }
    }
}
